package com.yj.auto.core.jfinal.context;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.Model;
import com.yj.auto.Constants;
import com.yj.auto.core.base.annotation.Table;
import com.yj.auto.utils.ClassUtil;

/**
 * 自动绑定（来自jfinal ext) 1.如果没用加入注解，必须以Controller结尾,自动截取前半部分为key 2.加入ModelBind的 获取
 * key
 */
public class AutoModelConfig {

	protected final Log logger = Log.getLog(getClass());

	private String dbname = Constants.DATABASE_NAME;

	private ActiveRecordPlugin arp;

	private List<Class<? extends Controller>> excludeClasses = new ArrayList<Class<? extends Controller>>();

	private List<String> includeJars = new ArrayList<String>();

	public AutoModelConfig(ActiveRecordPlugin arp) {
		this.arp = arp;
		config();
	}

	public AutoModelConfig(String dbname, ActiveRecordPlugin arp) {
		this.dbname = dbname;
		this.arp = arp;
		config();
	}

	public AutoModelConfig addJar(String jarName) {
		if (StrKit.notBlank(jarName)) {
			includeJars.add(jarName);
		}
		return this;
	}

	public AutoModelConfig addJars(String jarNames) {
		if (StrKit.notBlank(jarNames)) {
			addJars(jarNames.split(","));
		}
		return this;
	}

	public AutoModelConfig addJars(String[] jarsName) {
		includeJars.addAll(Arrays.asList(jarsName));
		return this;
	}

	public AutoModelConfig addJars(List<String> jarsName) {
		includeJars.addAll(jarsName);
		return this;
	}

	public AutoModelConfig addExcludeClass(Class<? extends Controller> clazz) {
		if (clazz != null) {
			excludeClasses.add(clazz);
		}
		return this;
	}

	public AutoModelConfig addExcludeClasses(Class<? extends Controller>[] clazzes) {
		excludeClasses.addAll(Arrays.asList(clazzes));
		return this;
	}

	public AutoModelConfig addExcludeClasses(List<Class<? extends Controller>> clazzes) {
		excludeClasses.addAll(clazzes);
		return this;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void config() {
		List<Class<? extends Model>> modelClasses = ClassUtil.findInClasspathAndJars(Model.class, includeJars);
		Table ModelBind = null;
		for (Class modelCls : modelClasses) {
			if (ClassUtil.isAbstract(modelCls))
				continue;
			if (excludeClasses.contains(modelCls)) {
				continue;
			}
			ModelBind = (Table) modelCls.getAnnotation(Table.class);
			if (ModelBind == null || StrKit.isBlank(ModelBind.name())) {
				continue;
			}

			// all default ,so not null
			if (StrKit.isBlank(ModelBind.dbname()) || StrKit.isBlank(dbname)) {
				logger.error("model.add is null");
				continue;
			}

			// join many database support
			if (dbname.equals(ModelBind.dbname())) {
				arp.addMapping(ModelBind.name(), ModelBind.key(), modelCls);
				logger.debug(ModelBind.dbname() + " --> model.add:" + modelCls + "," + ModelBind.name() + ", " + ModelBind.key());
			}

		}
	}

	public List<Class<? extends Controller>> getExcludeClasses() {
		return excludeClasses;
	}

	public void setExcludeClasses(List<Class<? extends Controller>> excludeClasses) {
		this.excludeClasses = excludeClasses;
	}

	public List<String> getIncludeJars() {
		return includeJars;
	}

	public void setIncludeJars(List<String> includeJars) {
		this.includeJars = includeJars;
	}

}
